/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.client.core.modal.grr;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intelligent.ispc.client.ex.dynamictable.DyAbstractTableModel;
import com.intelligent.ispc.common.utils.StringUtils;
import com.intelligent.ispc.core.dto.GrrViewDataDto;
import org.springframework.beans.BeanUtils;

import java.util.List;
import java.util.Map;

/**
 * Created by cherry on 2016/7/22.
 */
public class FixViewDataModel extends DyAbstractTableModel<GrrViewDataDto> {

    private String type;
    private int operator;
    private int trial;

    private List<GrrViewDataDto> data;
    private String[] columns;

    /**
     * fixViewDataModel constructor
     */
    public FixViewDataModel() {
        this.data = Lists.newArrayList();
    }

    @Override
    public int getColumnCount() {

        if (columns == null) {
            return 0;
        }

        return columns.length;
    }

    @Override
    public int getRowCount() {
        int rowCount = 0;
        if (data != null) {
            rowCount = data.size();
        }

        return rowCount;
    }

    @Override
    public String getColumnName(int col) {
        String name = "";
        if (columns != null && col < columns.length) {
            name = columns[col];
        }
        return name;
    }

    @Override
    public Object getValueAt(int row, int col) {
        if (data != null && row < data.size()) {
            GrrViewDataDto dto = data.get(row);
            String part = dto.getPart();
            String operatorTemp = dto.getOperator();
            String trialTemp = dto.getTrial();
            Boolean groupCheck = dto.getGroupCheck();
            Boolean check = dto.getCheck();
            switch (col) {
                case 0:
                    if ("check".equals(type)) {
                        return groupCheck == null ? Boolean.valueOf(true) : groupCheck;
                    } else {
                        return groupCheck == null ? Boolean.valueOf(false) : groupCheck;
                    }

                case 1:
                    return check == null ? Boolean.valueOf(false) : check;
                case 2:
                    if (!StringUtils.isBlank(part)) {
                        return part;
                    } else {
                        return "-";
                    }
                case 3:
                    return operatorTemp;
                case 4:
                    if (StringUtils.isNumeric(trialTemp)) {
                        return trial;
                    } else {
                        return "-";
                    }
                default:
                    return "_";
            }
        } else {
            return "";
        }
    }

    @Override
    public List getData() {
        return data;
    }

    @Override
    public void setData(List data) {
        if (data == null) {
            this.data = Lists.newArrayList();
        } else {
            this.data = data;
        }
        fireTableStructureChanged();
    }

    /**
     * set current row checkBox selected status
     *
     * @param aValue   is selected or not
     * @param rowIndex current row index
     */
    public void setCheckValue(boolean aValue, int rowIndex) {
        GrrViewDataDto dto = new GrrViewDataDto();
        BeanUtils.copyProperties(data.get(rowIndex), dto);
        dto.setCheck(aValue);
        data.set(rowIndex, dto);
        fireTableDataChanged();
    }

    /**
     * set current row group checkBox selected status
     *
     * @param aValue   is selected or not
     * @param rowIndex current row index
     */
    public void setGroupCheckValue(boolean aValue, int rowIndex) {

        if (data == null || data.size() <= rowIndex) {
            return;
        }

        data.get(rowIndex).setGroupCheck(aValue);
        List<Integer> firstChanges = getFirstPosition();
        int position = 0;
        int size = firstChanges.size();
        for (int i = 0; i < size; i++) {
            if (rowIndex == firstChanges.get(size - 1)) {
                position = data.size() - firstChanges.get(size - 1);
                break;
            } else {

                if (rowIndex == firstChanges.get(i)) {
                    position = firstChanges.get(i + 1) - firstChanges.get(i);
                    break;
                }
            }
        }

        if (aValue) {

            for (int i = rowIndex; i < rowIndex + position; i++) {
                data.get(i).setCheck(true);
            }
        } else {

            for (int i = rowIndex; i < rowIndex + position; i++) {
                data.get(i).setCheck(false);
            }
        }
        fireTableDataChanged();
    }

    /**
     * @return group checkBox locations
     */
    public List<Integer> getFirstPosition() {

        List<Integer> firstChanges = Lists.newArrayList();
        Map<String, Integer> partMaps = Maps.newHashMap();

        int count = 0;

        for (int i = 0; i < data.size(); i++) {

            if (!partMaps.containsKey(data.get(i).getPart())) {
                partMaps.put(data.get(i).getPart(), i);
                firstChanges.add(i);
                count = 0;
            } else {
                count++;
                if (count == operator * trial) {
                    firstChanges.add(i);
                    count = 0;
                }
            }
        }

        return firstChanges;
    }

    /**
     * @param columns table'columns name
     */
    public void setColumns(String[] columns) {
        if (columns == null) {
            this.columns = new String[0];
            return;
        }

        this.columns = new String[columns.length];
        System.arraycopy(columns, 0, this.columns, 0, columns.length);
        this.data = Lists.newArrayList();
    }

    public void setType(String type) {
        this.type = type;
    }

    /**
     * assign operator and trial
     *
     * @param operator part's operator count
     * @param trial    part's trial count
     */
    public void setOperatorAndTrial(int operator, int trial) {
        this.operator = operator;
        this.trial = trial;
    }
}
